package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import core.Util;

public class Proxy {

	private Socket serverConnect = null;

	private ServerSocket serverSocket = null;//connects to client
	private OutputStream srvOut=null;
	private InputStream srvIn=null;

	private Socket clientSocket = null;//connects to server
	private OutputStream cliOut=null;
	private InputStream cliIn=null;

	private InetAddress host = null;
	private boolean connected = false;
	private int cPort = 0;

	private boolean stop=false;

	//variables for commands
	private String delimit = "24eih89yfg57";
	private int leaveNum = -1;


	/**
	 * 
	 * @param serverport port that gets incoming connection to client
	 * @param h server
	 * @param clientport port that has outgoing connection to server
	 * @throws IOException
	 */
	public Proxy(int serverport, InetAddress h, int clientport) throws IOException{
		host = h;
		serverSocket = new ServerSocket(serverport);
		cPort = clientport;
	}

	/**
	 * Change the host the proxy will conect to, can only be done before it has connected.
	 * @param h The new host
	 * @return returns true if the host was changed
	 */
	public boolean changeHost(InetAddress h){
		if(!connected && h != null){
			host = h;
			return true;
		}
		return false;
	}

	public void close(){
		stop=true;
		try {
			cliOut.close();
			cliIn.close();
			clientSocket.close();
			srvOut.close();
			srvIn.close();
			serverSocket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * This method does not return.
	 */
	public void run(){

		try {
			System.out.println("Waiting for Client to connect...");
			serverConnect = serverSocket.accept();//this will wait until client connects to us.
			srvOut = serverConnect.getOutputStream();
			srvIn = serverConnect.getInputStream();

			System.out.println("Connecting to host @ "+host+":"+cPort);
			//if the server doesn't exist, this will fail.
			//doesn't seem to connect properly to the server.
			clientSocket = new Socket(host,cPort);
			cliOut = clientSocket.getOutputStream();
			cliIn = clientSocket.getInputStream();
			connected =true;
		} catch (IOException e2) {
			System.err.println("Couldn't connect:"+e2.getMessage());
		}

		System.out.println(clientSocket);
		System.out.println(serverSocket);
		int interval = 0;
		while(!stop){

			try {
				Thread.sleep(NetworkVars.defSleep);//as to not lag the cpu
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}

			try {
				if(cliIn.available() > 0){//this connects to the server
					byte send[] = new byte[cliIn.available()];
					cliIn.read(send);
					String out = Util.getString2(send);
					out("frm S: ",out);
					srvOut.write(send);
					interval=0;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			try {
				if(srvIn.available() > 0){//this connects to the client
					byte send[] = new byte[srvIn.available()];
					srvIn.read(send);
					String out = Util.getString2(send);
					out("frm C: ",out);
					cliOut.write(send);
					interval=0;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			interval++;
			if(interval > leaveNum && leaveNum > 0 ){
				//exit
				break;
			}
		}
		
		try {
			srvIn.close();
			srvOut.close();
			cliIn.close();
			cliOut.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

	public void command(String str){
		if(str.length() <= 0){
			return;
		}
		String out = "";
		String tmp;
		try {
			tmp = str.substring(str.indexOf(":")+1);
		} catch (Exception e1) {
			e1.printStackTrace();
			return;
		}
		try {
			switch(str.charAt(0)){
				case 'd':
					delimit = tmp;
					out = "Delimiter set to:"+tmp;
					break;
				case 's':
					cliOut.write(Util.getBytes(tmp));
					out("to s:",tmp);
					break;
				case 'c':
					srvOut.write(Util.getBytes(tmp));
					out("to c:",tmp);
					break;
				case 'l':
					//sets intervals to wait befor exiting
					leaveNum = Integer.parseInt(tmp);
					out = "Intervals to exit set to:"+tmp;
					break;
				case 'i':
					//print out all info, variables attached to proxy
					out = "l:"+leaveNum+"\n" +
							"d:"+delimit+"\n";
					break;
				case '/':
					break;
				default:
					out = "Not a command: "+str+"\n";
				case 'h':
					out += "d\tSets delimiter\n" +
							"c\tsends text to client\n" +
							"s\tsends text to server\n" +
							"h\tdisplays this\n" +
							"i\tintervals of "+NetworkVars.defSleep+"ms to wait befor exiting";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(out.length() > 0){
			System.out.println(out);
		}
	}

	public void out(String pre, String str){
		String[] arg0 = str.split(delimit);
		for(String s : arg0){
			System.out.println(pre + s);
		}
	}

}
